package system

import (
	"github.com/golang-jwt/jwt/v4"
	"time"
)

type (
	JwtOption func(c *claims)

	// Claims Claim是一些实体（通常指的用户）的状态和额外的元数据
	// json 中 key 会设置再ctx中
	// iss: Issuer 发行方
	// sub: Subject 主体
	// aud: Audience 目标方
	// exp: Expiration Time 过期时间
	// nbf: Not Before 早于该定义的时间的JWT不能被接受处理
	// iat: Issued At JWT发行时的时间戳
	// jti: JWT ID JWT的唯一标识
	claims struct {
		jwt.RegisteredClaims
		Uid         string   `json:"jwtUid"`
		UserName    string   `json:"jwtUserName"`
		Name        string   `json:"jwtName"`
		Roles       []string `json:"jwtRoles"`
		Permissions []string `json:"jwtPermissions"`
	}
)

// GenerateToken jwt Token 生成
// uid: 用户唯一标识
// secret: 公钥
// d: token 有效时间
func GenerateToken(uid string, secret string, d time.Duration, opts ...JwtOption) (string, error) {
	//设置token有效时间
	expireTime := time.Now().Add(d)
	c := &claims{
		RegisteredClaims: jwt.RegisteredClaims{
			// 过期时间
			ExpiresAt: &jwt.NumericDate{Time: expireTime},
		},
		Uid:         uid,
		UserName:    "",
		Name:        "",
		Roles:       []string{},
		Permissions: []string{},
	}

	for _, opt := range opts {
		opt(c)
	}

	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
	return tokenClaims.SignedString([]byte(secret))
}

// WithJwtUserName 用户名
func WithJwtUserName(s string) JwtOption {
	return func(c *claims) {
		c.UserName = s
	}
}

// WithJwtName 用户昵称
func WithJwtName(s string) JwtOption {
	return func(c *claims) {
		c.Name = s
	}
}

// WithJwtRoles 用户角色
func WithJwtRoles(roles []string) JwtOption {
	return func(c *claims) {
		c.Roles = append(make([]string, 0, len(roles)), roles...)
	}
}

// WithJwtPermissions 用户权限
func WithJwtPermissions(permissions []string) JwtOption {
	return func(c *claims) {
		c.Permissions = append(make([]string, 0, len(permissions)), permissions...)
	}
}
